#include <iostream>
#include <string>
#include "KvmClient.hpp"
#include "ImageProcess.hpp"
#include "BootOptionManager.hpp"
#include "PowerCtrl.hpp"
#include "GetVmmInfo.hpp"

char host[256], port[256], username[256], password[256], kvmMode[256];
char bootOption[2];
char powerControlOption[2];

void printMenu() {
    std::cout << "=============================\n"
              << "KVM Client Test Menu:\n"
              << "1. Open KVM Connection\n"
              << "2. Close KVM Connection\n"
              << "3. Exit\n"
              << "4. Get Boot Option\n"
              << "5. Set Boot Option\n"
              << "6. Power Control\n"
              << "7. Insert Virtual Media\n"
              << "8. Eject Virtual Media\n"
              << "=============================\n"
              << "Enter your choice: ";
}

void handleOpenKvm(KvmClient& kvmClient) {
    std::cout << "Enter host: "; std::cin >> host;
    std::cout << "Enter port: "; std::cin >> port;
    std::cout << "Enter username: "; std::cin >> username;
    std::cout << "Enter password: "; std::cin >> password;
    std::cout << "Enter KVM mode: "; std::cin >> kvmMode;

    int result = kvmClient.OpenKvm(host, port, username, password, kvmMode);
    if (result == EXIT_SUCCESS) {
        std::cout << "KVM connection opened successfully.\n";
    } else {
        std::cerr << "Failed to open KVM connection. errorCode: " << result << "\n";
    }

    std::fill_n(std::begin(password), sizeof(password), 0);
}

void handleCloseKvm(KvmClient& kvmClient, bool& isRunning) {
    int result = kvmClient.CloseKvm();
    if (result == 0) {
        std::cout << "KVM connection closed successfully.\n";
    } else {
        std::cerr << "Failed to close KVM connection. errorCode: " << result << "\n";
    }
    isRunning = false;
}

void handleGetBootOption(KvmClient& kvmClient) {
    BootOption option;
    int result = kvmClient.GetBootOption(option);
    if (result != 0) {
        std::cerr << "Failed to get boot option, errorCode: " << result << "\n";
        return;
    }

    std::cout << "Current boot option: ";
    switch (option) {
        case BootOption::None: std::cout << "None\n"; break;
        case BootOption::Hdd: std::cout << "Hdd\n"; break;
        case BootOption::Cd: std::cout << "Cd\n"; break;
        case BootOption::Floppy: std::cout << "Floppy\n"; break;
        case BootOption::Pxe: std::cout << "Pxe\n"; break;
        case BootOption::BiosSetup: std::cout << "BiosSetup\n"; break;
        default: std::cout << "Unknown\n"; break;
    }
}

void handleSetBootOption(KvmClient& kvmClient) {
    std::cout << "=============================\n"
        << "Enter boot option: \n"
        << "0: None\n"
        << "1: Hdd\n"
        << "2: Cd\n"
        << "3: Floppy\n"
        << "4: Pxe\n"
        << "5: BiosSetup\n"
        << "=============================\n"
        << "Enter your choice: ";
    std::cin >> bootOption;

    int result = kvmClient.SetBootOption(static_cast<BootOption>(std::stoi(bootOption)));
    if (result == 0) {
        std::cout << "Set boot option successfully.\n";
    } else {
        std::cerr << "Failed to set boot option, errorCode: " << result << "\n";
    }
}

void handlePowerControl(KvmClient& kvmClient) {
    std::cout << "=============================\n"
        << "Enter power control option: \n"
        << "0: Power On\n"
        << "1: Forced Power Off\n"
        << "2: Power Off\n"
        << "3: Forced Restart\n"
        << "4: Forced Power Cycle\n"
        << "5: Safe Power Cycle\n"
        << "=============================\n"
        << "Enter your choice: ";
    std::cin >> powerControlOption;

    int result = kvmClient.PowerControl(static_cast<PowerControlOption>(std::stoi(powerControlOption)));
    if (result == 0) {
        std::cout << "Power control successfully.\n";
    } else {
        std::cerr << "Failed to power control errorCode: " << result << "\n";
    }
}

void handleOpenVmm(KvmClient& kvmClient) {
    std::cout << "=============================\n"
        << "Enter mount type: \n"
        << "0: IsoImage\n"
        << "=============================\n"
        << "Enter your choice: ";
    int mountTypeInput;
    std::cin >> mountTypeInput;

    MountType mountType = static_cast<MountType>(mountTypeInput);

    std::cout << "=============================\n"
        << "Enter the path of the file to be mounted: ";
    std::string filePath;
    std::cin >> filePath;

    int result = kvmClient.OpenVmm(filePath, mountType);
    if (result == E_OK) {
        std::cout << "VMM connection opened successfully.\n";
    } else if (result == E_NOT_CONNECTED) {
        std::cerr << "Open Vmm failed: Not connected to KVM.\n";
    } else if (result == E_VMM_DISABLED) {
        std::cerr << "Open Vmm failed: VMM is disabled.\n";
    } else {
        std::cerr << "Open Vmm failed with error code: " << result << "\n";
    }
}

void handleCloseVmm(KvmClient& kvmClient) {
    int result = kvmClient.CloseVmm();
    if (result == E_OK) {
        std::cout << "Close Vmm successfully.\n";
    } else {
        std::cerr << "Close Vmm failed with error code: " << result << "\n";
    }
}

int main() {
    KvmClient kvmClient;
    kvmClient.SetLogHandler([](const std::string& message) { std::cout << message << std::endl; });
    kvmClient.SetErrorHandler([](const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; });
    kvmClient.SetCloseHandler([](const uint16_t& closeCode) {
        std::cout << "Connection closed. closeCode: " << closeCode << std::endl;
    });

    ImageProcess imageProcess(kvmClient);
    BootOptionManager bootOptionManager(kvmClient);
    PowerCtrl powerCtrl(kvmClient);
    GetVmmInfo getVmmInfo(kvmClient);

    bool isRunning = true;
    const int optionOpen = 1;
    const int optionClose = 2;
    const int optionExit = 3;
    const int optionGetBootOption = 4;
    const int optionSetBootOption = 5;
    const int optionPowerControl = 6;
    const int optionInsertVirtualMedia = 7;
    const int optionEjectVirtualMedia = 8;
    while (isRunning) {
        printMenu();
        int choice;
        std::cin >> choice;
        switch (choice) {
            case optionOpen: handleOpenKvm(kvmClient); break;
            case optionClose: handleCloseKvm(kvmClient, isRunning); break;
            case optionExit: isRunning = false; std::cout << "Exiting...\n"; break;
            case optionGetBootOption: handleGetBootOption(kvmClient);break;
            case optionSetBootOption: handleSetBootOption(kvmClient);break;
            case optionPowerControl: handlePowerControl(kvmClient);break;
            case optionInsertVirtualMedia: handleOpenVmm(kvmClient);break;
            case optionEjectVirtualMedia: handleCloseVmm(kvmClient);break;
            default: std::cerr << "Invalid choice. Please try again.\n"; break;
        }
    }
    return 0;
}